﻿//module;
/**
 * @author rayzhang
 * @details 浮点数比较函数
 */
#include <cmath>
#include <type_traits>
#include "../libflow_global.h"
//export module libflow.float_comparisons;
/*export*/ namespace flow
{

// 定义浮点数概念
template <typename T>
concept FloatingPoint = std::is_floating_point_v<T>;

// 默认的浮点数精度
inline constexpr float defaultFloatEpsilon   = 1e-6f;
inline constexpr double defaultDoubleEpsilon = 1e-15;

constexpr double max_double()
{
    return std::numeric_limits<double>::max();
}
constexpr double min_double()
{
    return std::numeric_limits<double>::lowest();
}

template <FloatingPoint T>
bool isEqual(T a, T b, T epsilon = std::is_same_v<std::decay_t<T>, float> ? defaultFloatEpsilon : defaultDoubleEpsilon)
{
    return std::fabs(a - b) <= epsilon;
}

template <FloatingPoint T>
bool isGreater(T a, T b, T epsilon = std::is_same_v<std::decay_t<T>, float> ? defaultFloatEpsilon : defaultDoubleEpsilon)
{
    return (a - b) > epsilon;
}

template <FloatingPoint T>
bool isLesser(T a, T b, T epsilon = std::is_same_v<std::decay_t<T>, float> ? defaultFloatEpsilon : defaultDoubleEpsilon)
{
    return (b - a) > epsilon;
}

template <FloatingPoint T>
bool isGreaterThanOrEqual(T a, T b, T epsilon = std::is_same_v<std::decay_t<T>, float> ? defaultFloatEpsilon : defaultDoubleEpsilon)
{
    return !isLesser(a, b, epsilon);
}

template <FloatingPoint T>
bool isLesserThanOrEqual(T a, T b, T epsilon = std::is_same_v<std::decay_t<T>, float> ? defaultFloatEpsilon : defaultDoubleEpsilon)
{
    return !isGreater(a, b, epsilon);
}

template <template <typename...> class Container, std::floating_point T>
int indexOfValue(const Container<T>& container, T value)
{
    for (int i = 0; i < container.size(); ++i) {
        if (isEqual(container[i], value)) {
            return i;
        }
    }
    return -1;
}

} // namespace flow